#include "drv_iic.h"
#include "FreeRTOS.h"
#include "task.h"
#include "drv_time.h"
void drv_iic_init(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void drv_iic_in(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void drv_iic_out(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void drv_iic_start(void)
{
	SCL_L;
	drv_iic_out();
	
	taskENTER_CRITICAL();
	SDA_H;
	SCL_H;	
	drv_tim6_us(5);
	SDA_L;	
	drv_tim6_us(5);
	SCL_L;
	taskEXIT_CRITICAL();
}
void drv_iic_stop(void)
{
	SCL_L;
	drv_iic_out();

	taskENTER_CRITICAL();
	SDA_L;
	SCL_H;	
	drv_tim6_us(5);
	SDA_H;	
	drv_tim6_us(5);
	taskEXIT_CRITICAL();
}
void drv_iic_sendACK(void)
{
	SCL_L;
	drv_iic_out();

	taskENTER_CRITICAL();
	SDA_L;
	SCL_H;	
	drv_tim6_us(5);
	SCL_L;
	taskEXIT_CRITICAL();
}
void drv_iic_sendnoACK(void)
{
	SCL_L;
	drv_iic_out();

	taskENTER_CRITICAL();
	SDA_H;
	SCL_H;	
	drv_tim6_us(5);
	SCL_L;
	taskEXIT_CRITICAL();
}
uint8_t drv_iic_waitACK(void)
{
	uint16_t tim_out = 0;
	SCL_L;
	drv_iic_in();

	taskENTER_CRITICAL();
	SCL_H;	
	while(READ_SDA)
	{
		tim_out++;
		if(tim_out > 500)
		{
			drv_iic_stop();
			taskEXIT_CRITICAL();
			return NOACK;
		}
	}
	SCL_L;
	taskEXIT_CRITICAL();
	return ACK;
}
void drv_iic_senddata(uint8_t data)
{
	uint8_t i=0;
	SCL_L;
	drv_iic_out();

	taskENTER_CRITICAL();
	for(i=0;i<8;i++)
	{
		if(data & 0x80)
		{
			SDA_H;// 如果最高位为1，设置SDA为高电平
		}
		else
		{
			SDA_L;
		}
        
		SCL_H;
		drv_tim6_us(2);
		SCL_L;
		drv_tim6_us(2);
		data = data << 1;
	}
	taskEXIT_CRITICAL();
}
uint8_t drv_iic_readdata(uint8_t flg_ack)
{
	uint8_t receive = 0,i = 0;
	SCL_L;
	drv_iic_in();

	taskENTER_CRITICAL();
	for(i=0;i<8;i++)
	{
		receive = receive << 1;
		SCL_H; // 时钟线拉高，从机可以发送数据
		if(READ_SDA)
		{
			receive |= 0x01;// 如果SDA为高，设置最低位为1
		}
		drv_tim6_us(1);
		SCL_L;
		drv_tim6_us(1);		
	}
	//循环 8 次后，先接收的 “最高位” 会被左移到接收缓存的最高位，后接收的 “低位” 会留在缓存的低位。
	if(flg_ack)
	{
		drv_iic_sendACK();
	}
	else
	{
		drv_iic_sendnoACK();
	}
	SCL_L;
	taskEXIT_CRITICAL();
	return receive;
}
